#include "ipc.h"

#ifdef WIN3264
#include <windows.h>
#else
#include <fcntl.h>
#include <semaphore.h>
#include <errno.h>
#endif

semaphore_status_T create_semaphore( semaphore_handle_T handle, char* key, int initial_value )
{
  semaphore_status_T status = SEMAPHORE_OK;

  #ifdef WIN3264
  HANDLE h = CreateSemaphore( 0, initial_value, MAXLONG, key );
  handle = (void*)h;
  if ( handle == NULL ) {
    DWORD err = GetLastError();
    switch( err ) {
    case ERROR_NO_SYSTEM_RESOURCES:
    case ERROR_NOT_ENOUGH_MEMORY:
      status = SEMAPHORE_MEMORY_ERROR;
      break;
    case ERROR_ACCESS_DENIED:
      status = SEMAPHORE_PERMISSION_ERROR;
      break;
    default:
      status = SEMAPHORE_UNKNOWN;
    };
  }
  #else
  sem_t* sem;
  sem = sem_open( key, O_CREAT|O_EXCEL, (S_IRWXU|S_IRWXG|S_IRWXO), initial_value );
  handle = (void*)sem;
  if ( sem == SEM_FAILED ) {
    switch( errno ) {
    case EEXIST :
      status = SEMAPHORE_EXISTS;
      break;
    case EACCES :
      status = SEMAPHORE_PERMISSION_ERROR;
      break;
    case ENOMEM :
      status = SEMAPHORE_MEMORY_ERROR:
      break;
    case EINVAL :
      status = SEMAPHORE_VALUE_ERROR;
      break;
    default:
      status SEMAPHORE_UNKNOWN;
    };
  }
  #endif

  return status;
}

semaphore_status_T aquire_semaphore( semaphore_handle_T handle )
{
  semaphore_status_T status = SEMAPHORE_OK;

  #ifdef WIN3264
  WaitForSingleObject( (HANDLE)handle, INFINITE );
  // TODO check error
  #else
  sem_wait( (sem_t*)handle );
  // TODO check error
  #endif

  return status;
}

semaphore_status_T release_semaphore( semaphore_handle_T handle )
{
  semaphore_status_T status = SEMAPHORE_OK;

  #ifdef WIN3264
  ReleaseSemaphore( (HANDLE)handle, 1, 0 );
  // TODO check error
  #else
  sem_post( (sem_t*)handle );
  // TODO check error
  #endif

  return status;
}

int destroy_semaphore( semaphore_handle_T handle )
{
  semaphore_status_T status = SEMAPHORE_OK;

  #ifdef WIN3264
  CloseHandle( (HANDLE)handle );
  // TODO check error
  #else
  sem_destroy( (sem_t*)handle );
  // TODO check error
  #endif

  return status;
}
